package cn.demoncat.util.pay.yeepay.entity;

import cn.demoncat.util.exception.BizErrorRuntimeException;
import cn.demoncat.util.exception.BizRuntimeException;
import cn.demoncat.util.lang.StringUtil;
import cn.demoncat.util.lang.constant.StringConstant;
import cn.demoncat.util.pay.constant.PayMsgs;
import cn.demoncat.util.pay.yeepay.constant.YeepayApi;
import cn.demoncat.util.pay.yeepay.constant.YeepayLogs;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.yeepay.g3.sdk.yop.client.YopResponse;
import com.yeepay.g3.sdk.yop.error.YopError;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.util.Map;

/**
 * 响应参数
 *
 * @author 延晓磊
 * @since 2020年10月17日
 */
public class YeepayResult {

    // 请求接口
    protected YeepayApi api;
    // 响应结果
    protected YopResponse response;
    // 响应数据
    protected JSONObject map;

    private static final Logger LOG = LoggerFactory.getLogger(YeepayResult.class);

    public YeepayResult() {
        super();
    }

    /**
     * 构建响应
     * 
     * @param api
     * @param response
     * 
     * @author 延晓磊
     * @since 2020年10月22日
     */
    public YeepayResult(YeepayApi api, YopResponse response) {
        this.api = api;
        this.response = response;
        LOG.debug("接收响应：api = {}, param = {}", api.getName(), response);
        if (response.isSuccess()) {
            // 请求成功（可能业务失败）
            this.map = response.getResult() == null || !(response.getResult() instanceof  Map) ? new JSONObject() : new JSONObject((Map<String, Object>) this.getResponse().getResult());
        }else{
            // 请求错误（参数错误，鉴权失败，授权有误，服务故障）
            if(response.getError().getCode().equalsIgnoreCase("40044")){
                // 业务处理失败
                if(api.getUrl().equalsIgnoreCase(YeepayApi.TRADE_BILL_DOWNLOAD.getUrl())){
                    // 交易账单下载
                    if(response.getError().getSubCode().equalsIgnoreCase("isp.code.TC00000004")){
                        // 对账文件不存在 - 忽略
                        return;
                    }
                }
            }
            // 其它错误
            LOG.warn(YeepayLogs.REQUEST_ERROR, api.getName(), api.getUrl(), response.getRequestId(), response.getError());
            throw new BizErrorRuntimeException(PayMsgs.REQUEST_ERROR + response.getError().getMessage() + (StringUtils.isBlank(response.getError().getSubMessage()) ? StringConstant.EMPTY : (" - " + response.getError().getSubMessage())));
        }
    }

    /**
     * 构建子类对象
     *
     * @param other 响应结果
     * @param clazz 子类
     * @return
     */
    public static <T extends YeepayResult>T build(YeepayResult other, Class<T> clazz){
        // 拷贝业务属性
        T o = other.map.toJavaObject(clazz);
        // 拷贝基础属性
        o.api = other.api;
        o.response = other.response;
        o.map = other.map;
        return o;
    }

    /**
     * 校验业务状态码（子类创建前，先check业务状态，为success再拷贝响应参数）
     *
     * @param codeName      状态码参数：默认code
     * @param messageName   消息参数：默认message
     * @param successCode   成功状态码：如果为空则所有code都认为是失败，如果非空则等于code为成功
     * @return this
     *
     * @author 延晓磊
     * @since 2020年10月22日
     */
    public YeepayResult check(String codeName, String messageName, String successCode){
        // 业务状态码参数
        if (StringUtils.isBlank(codeName)) {
            codeName = "code";
        }
        if (StringUtils.isBlank(messageName)) {
            messageName = "message";
        }
        // 业务状态校验
        String code = StringUtil.toString(this.getMap().get(codeName));
        // 状态码非空
        if (StringUtils.isNotBlank(code)) {
            // 非指定码
            if (StringUtils.isBlank(successCode) || !successCode.equals(code)) {
                YopError error = new YopError();
                error.setCode(code);
                error.setMessage(StringUtil.toDefault(StringUtil.toString(this.getMap().get(messageName)),"状态错误"));
                LOG.warn(YeepayLogs.REQUEST_WARN, api.getName(), api.getUrl(), response.getRequestId(), error);
                throw new BizRuntimeException(PayMsgs.REQUEST_ERROR + error.getMessage());
            }
        }
        return this;
    }

    /**
     * 校验参数是否一致（防止数据不一致，只支付字符串类型）
     *
     * @param paramName
     * @param requestParam
     * @param responseParam
     * @return
     */
    public YeepayResult checkParam(String paramName, Object requestParam, Object responseParam){
        if (requestParam.equals(responseParam)) {
            return this;
        }else{
            // 数字校验
            if (requestParam instanceof Number) {
                if (responseParam != null &&  ((Number) requestParam).doubleValue() == ((Number) responseParam).doubleValue()) {
                    return this;
                }
            }
            // 参数不一致
            LOG.warn(YeepayLogs.REQUEST_INCONSISTENT, api.getName(), api.getUrl(), response.getRequestId(), paramName, requestParam, responseParam);
            throw new BizRuntimeException(PayMsgs.REQUEST_INCONSISTENT);
        }
    }

    /**
     * 请求接口
     * 
     * @return  api
     * 
     * @author 延晓磊
     * @since 2020年10月22日
     */
    @JSONField(serialize=false,deserialize=false)
    public YeepayApi getApi() {
        return api;
    }

    /**
     * 响应结果
     * 
     * @return 易宝响应结果
     * 
     * @author 延晓磊
     * @since 2020年10月22日
     */
    @JSONField(serialize=false,deserialize=false)
    public YopResponse getResponse() {
        return response;
    }

    /**
     * 获取结果
     *
     * @return Map
     * 
     * @author 延晓磊
     * @since 2020年10月22日
     */
    @JSONField(serialize=false,deserialize=false)
    public JSONObject getMap(){
        return map;
    }

    /**
     * 获取结果
     *
     * @return InputStream
     * 
     * @author 延晓磊
     * @since 2020年10月22日
     */
    @JSONField(serialize=false,deserialize=false)
    public InputStream getStream(){
        return response.getFile();
    }

}
